﻿#region Copyright
//Copyright 2012 Phelon Aka. Jon H.
/*
    This file is part of BGBuddy - Ultimate PVP Suite.

    BGBuddy - Ultimate PVP Suite is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BGBuddy - Ultimate PVP Suite is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>
 */
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Styx.Plugins;
using Styx;
using Styx.Helpers;
using Styx.CommonBot.POI;
using Styx.Pathing;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Tripper.Tools.Math;

namespace UltimatePvPSuite
{
    public static class Unit
    {
        public static WoWUnit Target = null;
        private static List<string> HealerList = new List<string>();
        private static List<string> CasterList = new List<string>();
        private static List<string> MeleeList = new List<string>();
        private static List<string> TankList = new List<string>();
        private static List<string> PlayerInfo = new List<string>();
        /// <summary>
        /// Check to see if we are constantly facing.
        /// </summary>
        public static void CheckFace()
        {
            if (!StyxWoW.Me.IsFacing(StyxWoW.Me.CurrentTarget))
            {
                //Logger.Write("Facing.");
                WoWMovement.ConstantFace(StyxWoW.Me.CurrentTarget.Guid);
            }
        }
        /// <summary>
        /// Get Degree of Current Target
        /// </summary>
        public static double GetDegree
        {
            get
            {
                double d = Math.Atan2((StyxWoW.Me.CurrentTarget.Y - StyxWoW.Me.Y), (StyxWoW.Me.CurrentTarget.X - StyxWoW.Me.X));

                double r = d - StyxWoW.Me.CurrentTarget.Rotation; 	  // substracting object rotation from absolute rotation
                if (r < 0)
                    r += (Math.PI * 2);

                return WoWMathHelper.RadiansToDegrees((float)r);
            }
        }
        /// <summary>
        ///   Gets the nearby friendly players within 40 yards.
        /// </summary>
        /// <value>The nearby friendly players.</value>
        public static IEnumerable<WoWPlayer> NearbyFriendlyPlayers
        {
            get { return ObjectManager.GetObjectsOfType<WoWPlayer>(true, true).Where(p => p.DistanceSqr <= 40 * 40 && p.IsFriendly).ToList(); }
        }
        /// <summary>
        ///   Gets the nearby unfriendly units within 40 yards.
        /// </summary>
        /// <value>The nearby unfriendly units.</value>
        public static IEnumerable<WoWUnit> NearbyUnfriendlyUnits
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => ValidUnit(p) && p.DistanceSqr <= 40 * 40).ToList(); }
        }
        /// <summary>
        /// Gets Nearby Units who are Tagged by me.
        /// </summary>
        public static IEnumerable<WoWUnit> NearbyUnitsInCombatWithMe
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => ValidUnit(p) && p.DistanceSqr <= 40 * 40 && p.Combat && p.TaggedByMe).ToList(); }
        }
        /// <summary>
        /// Checks to See if it is a Valid Enemy Unit
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public static bool ValidUnit(WoWUnit p)
        {
            // Ignore friendlies!
            if (p.IsFriendly)
                return false;

            // Duh
            if (p.IsDead)
                return false;

            // If its a pet, lets ignore it please.
            if (p.IsPet || p.OwnedByRoot != null)
                return false;

            // And ignore critters/non-combat pets
            if (p.IsNonCombatPet || p.IsCritter)
                return false;

            return true;
        }
        /// <summary>
        /// Gets the Class Spec of all players in the Battleground and adds them to lists.
        /// </summary>
        private static void PlayerSpecCheck()
        {
            try
            {
                string Faction = "1";
                if (StyxWoW.Me.IsHorde)
                    Faction = "0";
                if (Lua.GetReturnVal<int>("return GetNumBattlefieldScores()", 0) > 0)
                {
                    PlayerInfo.Clear();
                    HealerList.Clear();
                    MeleeList.Clear();
                    TankList.Clear();
                    CasterList.Clear();
                    using (StyxWoW.Memory.AcquireFrame())
                    {
                        for (int i = 0; i <= Lua.GetReturnVal<int>("return GetNumBattlefieldScores()", 0); i++)
                        {
                            int p = 0;
                            string PlayerName = "";

                            PlayerInfo = Lua.GetReturnValues("return GetBattlefieldScore(" + i + ")");
                            foreach (string info in PlayerInfo)
                            {
                                p++;

                                if (p == 1)
                                {
                                    //Logger.Write("Name: " + PlayerName);
                                    PlayerName = info;
                                }
                                if (p == 6)
                                {
                                    if (info == Faction)
                                    {
                                        //Logger.Write("Faction: " + PlayerName);
                                        break;
                                    }
                                }
                                if (p == 9)
                                {
                                    if (info == "Rogue")
                                    {
                                        MeleeList.Add(PlayerName);
                                        break;
                                    }
                                    if (info == "Warlock" || info == "Mage")
                                    {
                                        CasterList.Add(PlayerName);
                                        break;
                                    }
                                }
                                if (p == 16)
                                {
                                    if (info.Contains("Resto") || info.Contains("Disc") || info.Contains("Holy"))
                                    {
                                        //Logger.Write("Adding " + PlayerName + " as a " + info + " healer!");
                                        HealerList.Add(PlayerName);
                                        break;
                                    }
                                    else if (info.Contains("Prot") || info.Contains("Blood"))
                                    {
                                        TankList.Add(PlayerName);
                                        break;
                                    }
                                    else if (info.Contains("Fury") || info.Contains("Arms") ||
                                        info.Contains("Frost") || info.Contains("Unholy") ||
                                        info.Contains("Retribution") || info.Contains("Feral") || info.Contains("Enhancement"))
                                    {
                                        MeleeList.Add(PlayerName);
                                        break;
                                    }
                                    else
                                    {
                                        CasterList.Add(PlayerName);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception exg) { Logger.Write("" + exg); }
        }

        /// <summary>
        /// Finds the best target based on spec.
        /// </summary>
        /// <param name="role"></param>
        /// <param name="range"></param>
        /// <returns></returns>
        public static WoWPlayer ValidTarget(string role, int range)
        {
            PlayerSpecCheck();
            using (StyxWoW.Memory.AcquireFrame())
            {
                return (from Unit in ObjectManager.GetObjectsOfType<WoWPlayer>(false)
                        orderby Unit.MaxHealth
                        where Unit.IsAlive
                        where Unit.IsPlayer
                        where Unit.Distance < range
                        where !Unit.IsFriendly
                        where !Unit.IsPet
                        where !Unit.HasAura("Spirit of Redemption")
                        where !Unit.HasAura("Blessing of Protection")
                        where !Unit.HasAura("Divine Shield")
                        where !Unit.HasAura("Iceblock")
                        where !Unit.HasAura("Cyclone")
                        where !Unit.HasAura("Cloak of Shadows")
                        where !Unit.HasAura("Anti-Magic Shell")
                        where Navigator.CanNavigateFully(StyxWoW.Me.Location, Unit.Location)
                        where CheckHealerList(Unit) && role == "Healer" ||
                        CheckCasterList(Unit) && role == "Caster" ||
                        CheckMeleeList(Unit) && role == "Melee" ||
                        CheckTankList(Unit) && role == "Tank"
                        select Unit).FirstOrDefault();
            }
        }

        /// <summary>
        /// Checks for Player in Healers List
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool CheckHealerList(WoWPlayer unit)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                foreach (string healer in HealerList)
                {
                    if (healer.Contains(unit.Name))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Checks for Player in Casters List
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool CheckCasterList(WoWPlayer unit)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                foreach (string caster in CasterList)
                {
                    if (caster.Contains(unit.Name))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Checks for Player in Melee List
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool CheckMeleeList(WoWPlayer unit)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                foreach (string melee in MeleeList)
                {
                    if (melee.Contains(unit.Name))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// Checks for Player in Tank List
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool CheckTankList(WoWPlayer unit)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                foreach (string tank in TankList)
                {
                    if (tank.Contains(unit.Name))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}
